package classificator.tree;


import classificator.data.DiscreteAttribute;
import classificator.data.Data;
import classificator.data.Attribute;

/**Estende la classe SplitNode e modella l'entità nodo di split relativo ad un attributo indipendente discreto. 
 *
 * @author 467644
 */
class DiscreteNode extends SplitNode{
    /**Istanzia un oggetto invocando il costruttore della superclasse con il parametro attribute
     * 
     * @param trainingSet training set complessivo
     * @param beginExampleIndex indice iniziale del sotto-insieme di training
     * @param endExampleIndex indice finale del sotto-insieme di training
     * @param attribute attributo indipendente sul quale si definisce lo split
     */
    DiscreteNode(Data trainingSet, int beginExampleIndex, int endExampleIndex, DiscreteAttribute attribute){
        super(trainingSet, beginExampleIndex, endExampleIndex, attribute);
    }

    /**(Implementazione da class abstract): istanzia oggetti SpliInfo con ciascuno dei valori 
     * discreti relativamente al sotto-insieme di training corrente, 
     * quindi popolano l'arraylist mapSplit. 
     * 
     * @param trainingSet training set complessivo
     * @param beginExampleIndex indice iniziale del sotto-insieme di training
     * @param endExampleIndex indice finale del sotto-insieme di training
     * @param attribute attributo indipendente sul quale si definisce lo split
     */
    @Override
    void setSplitInfo(Data trainingSet, int beginExampleIndex, int endExampleIndex, Attribute attribute) {
        Object nextSV;
        int figlio = 0;
        int beginSplit = beginExampleIndex;
        Object currentSV = trainingSet.getExplanatoryValue(beginExampleIndex, attribute.getIndex());
        // determina quando varia il valore in 'attribute' tra l'attuale e il successivo splitvalue
        for (int i=beginExampleIndex+1; i<=endExampleIndex; i++) {
            nextSV = trainingSet.getExplanatoryValue(i, attribute.getIndex());
            if (!currentSV.equals(nextSV)){
    		mapSplit.add(new SplitInfo(currentSV, beginSplit, i-1, figlio ));
    		currentSV = nextSV;
                beginSplit = i;
                figlio++;
            }
        }
        mapSplit.add(new SplitInfo(currentSV, beginSplit, endExampleIndex, figlio));
    }

    /**(Implementazione da class abstract): effettua il confronto del valore in input rispetto 
     * a tutti gli split mapSplit e restituisce l'identificativo dello split con cui il test è positivo 
     * 
     * @param value valore discreto dell'attributo che si vuole testare rispetto a tutti gli split 
     * @return numero del ramo di split
     */
    @Override
    int testCondition (Object value){
        for (int i=0; i<mapSplit.size(); i++){
            //if (mapSplit.get(i).getSplitValue().equals(value))
            if (mapSplit.get(i).equals(value))
                return i;
        }
        return -1;
        // /TODO aggiungere eccezione.
        //throw new RuntimeException("Node doesn't have correct value.");
    }
    
    @Override
    public String toString(){
        return "[DISCRETE] " + super.toString();
    }
}